package com.ribbon.config;


import com.alibaba.cloud.nacos.NacosDiscoveryProperties;
import com.alibaba.cloud.nacos.NacosServiceManager;
import com.alibaba.cloud.nacos.ribbon.NacosServer;
import com.alibaba.nacos.api.exception.NacosException;
import com.alibaba.nacos.api.naming.NamingService;
import com.alibaba.nacos.api.naming.pojo.Instance;
import com.alibaba.nacos.client.naming.core.Balancer;
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.BaseLoadBalancer;
import com.netflix.loadbalancer.Server;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.util.List;
import java.util.stream.Collectors;

//自定义权重算法规则
@Component
public class ClusterWeightRule extends AbstractLoadBalancerRule {

    @Autowired
    private NacosDiscoveryProperties ndp;
    @Autowired
    private NacosServiceManager nsm;

    @Override
    public Server choose(Object key) {
        //通过服务发现得到服务筛选跟当前服务的节点的集群相同的所有节点，然后在剩下的节点当中按照权重算法来返回一个访问
        //1.从注册信息得到当前这次请求正在访问的服务的服务名（得到要访问服务的服务名）
        //2.通过服务名得到该服务的所有健康的节点
        //3.得到当前发请求节点的注册信息（获取当前节点的集群名）
        //4.筛选出跟当前服务节点集群名相同的节点
        //5.如果得到了，就在节点中通过权重算法选一个，否则就在其它节点中通过权重算法选一个
        String toName = ((BaseLoadBalancer) getLoadBalancer()).getName();//要访问的服务
        String fromName = ndp.getService();//当前服务
        String clusterName = ndp.getClusterName();//当前集群名
        String namespace = ndp.getNamespace();//当前命名空间Id
        String group = ndp.getGroup();//当前命名空间组名

        NamingService client = nsm.getNamingService(ndp.getNacosProperties());
        try {
            List<Instance> instances = client.selectInstances(toName, group, true);
            if (!ObjectUtils.isEmpty(instances)) {//查得到当前命名空间下的所有节点
                //选择集群名与当前名相同的
                List<Instance> nodes = instances.stream().filter(o -> o.getClusterName().equals(clusterName))
                        .collect(Collectors.toList());
                if (ObjectUtils.isEmpty(nodes)) nodes = instances;
                //采用权重算法选一个节点
               return new NacosServer(MyBalancer.getRandomWeight(nodes));
            }
        } catch (NacosException e) {
           e.printStackTrace();
        }
        return null;
    }

    @Override
    public void initWithNiwsConfig(IClientConfig iClientConfig) {
    }

    static class MyBalancer extends Balancer {
        public static Instance getRandomWeight(List<Instance> hosts){
            return Balancer.getHostByRandomWeight(hosts);
        }
    }

}
